package com.learning.optimize.jdk.genericity;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

/**
 * ClassName: Genericity
 * Description: 泛型通配符与边界符
 * Date: 2018/7/25 13:08 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class Genericity {

    public static void main(String[] args) {
        test();
//        wildcard();
    }

    /**
     * 集合：没有泛型和使用泛型
     */
    static void test() {
        ArrayList list = new ArrayList();
        list.add(1);
        list.add("Sam");
        list.add(false);
        list.add(new Date());

        Object o = list.get(0);
        int obj = (int) o;
        System.out.println(obj);

        String objStr = (String) list.get(1);
        System.out.println(objStr);

        boolean flag = (boolean) list.get(2);
        System.out.println(flag);

        Date date = (Date) list.get(3);
        System.out.println(date);

        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("Sam");
        // 编译不过
//        arrayList.add(new Date());
    }

    /**
     * 参数化类型与原始类型的兼容性
     */
    static void test2() {
        // 参数化类型可以引用一个原始类型的对象，但是编译器会警告
        ArrayList<String> c = new ArrayList();

        // 原始类型可以引用一个参数化类型的对象
        ArrayList c2 = new ArrayList<String>();

        // 参数化类型不考虑类型参数的继承关系

        // 编译器报错：原因在于 v中拿到的是String，而实际上ArrayList中则为Object，其中有可能是 Date
        // ArrayList<String> v = new ArrayList<Object>();

        // 编译器报错
        // ArrayList<Object> v2 = new ArrayList<String>();


        // 编译器报错：在创建数组实例时，数组的元素不能使用参数化的类型
        // ArrayList<Integer> v3[] = new ArrayList<Integer>[10];

    }


    /**
     * 通配符与边界限定
     */
    static void wildcard() {
        ArrayList<Integer> list = Lists.newArrayList(1, 2);
        printCollection(list);

        ArrayList<String> list2 = Lists.newArrayList("sam", "rabby");
        // 编译不过
////        printCollection2(list2);

        // 使用通配符
        printCollection3(list);
        printCollection3(list2);


    }


    public static void printCollection(Collection<Integer> collection) {

    }

    public static void printCollection2(Collection<Object> collection) {

    }

    /**
     * 通配符方法
     *
     * @param collection
     */
    public static void printCollection3(Collection<?> collection) {
        for (Object o : collection) {
            System.out.println(o);
        }
    }

    /**
     * 通配符边界
     *
     * @param collection
     */
    public static void printCollection4(Collection<? extends Number> collection) {
        for (Object o : collection) {
            System.out.println(o);
        }
    }

    /**
     * 无边界
     *
     * @param anArray
     * @param elem
     * @param <T>
     * @return
     */
    public static <T> int countGreaterThan(T[] anArray, T elem) {
        int count = 0;
        for (T e : anArray) {
            /*if (e > elem) { // compiler error
                ++count;
            }*/
        }
        return count;
    }

    /**
     * 泛型边界符
     *
     * @param anArray
     * @param elem
     * @param <T>
     * @return
     */
    public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {
        int count = 0;
        for (T e : anArray) {
            if (e.compareTo(elem) > 0) {
                ++count;
            }
        }
        return count;
    }
}
